/*
 * ShotSocketSender.cpp
 *
 *  Created on: Oct 6, 2012
 *      Author: Administrator
 */

#include "ShotSocketSender.h"

using namespace Osp::Base;
using namespace Osp::Net;
using namespace Osp::Net::Sockets;
using namespace Osp::Base::Utility;

ShotSocketSender::ShotSocketSender() {
	result r = E_SUCCESS;

	isReadyToSend = false;
	socket = new Socket();

	r = socket->Construct(NET_SOCKET_AF_IPV4, NET_SOCKET_TYPE_STREAM, NET_SOCKET_PROTOCOL_TCP);
	AppLog("Socket Construct response: (%s)\n", GetErrorMessage(r));

//	r = socket->SetSockOpt(NET_SOCKET_SOL_SOCKET , NET_SOCKET_TCP_NODELAY, 1);
//	AppLog("Socket SetSockOpt response: (%s)\n", GetErrorMessage(r));

	r = socket->AddSocketListener(*this);
	AppLog("Socket AddSocketListener response: (%s)\n", GetErrorMessage(r));

	r = socket->AsyncSelectByListener(NET_SOCKET_EVENT_CONNECT
			| NET_SOCKET_EVENT_CLOSE
			| NET_SOCKET_EVENT_READ
			| NET_SOCKET_EVENT_WRITE);
	AppLog("Socket AsyncSelectByListener response: (%s)\n", GetErrorMessage(r));

	NetEndPoint* point = new NetEndPoint(Ip4Address(L"192.168.0.184"), 8080);

	r = socket->Connect(*point);
	AppLog("Socket Connect response: (%s)\n", GetErrorMessage(r));

	///
}

ShotSocketSender::~ShotSocketSender() {
	result r = E_SUCCESS;
	r = socket -> Close();
	AppLog("Socket Close response: (%s)\n", GetErrorMessage(r));
}

void
ShotSocketSender::SendShot(Shot* shot) {

	while (!isReadyToSend) {
		Osp::Base::Runtime::Thread::GetCurrentThread()->Sleep(1000);
	}

	result r = E_SUCCESS;

//	String delimiterStr(L"\n\r");
	String delimiterStr(L"");

	String headerStr(L"POST /beholder-master/post HTTP/1.1\n\r");
	headerStr.Append(L"Host: 192.168.0.184\n\r");
//	headerStr.Append(L"Content-Length:");
//	headerStr.Append(shot->GetSize());
	headerStr.Append(L"\n\r");
	headerStr.Append(L"\n\r");

	ByteBuffer* requestBuffer = new ByteBuffer();
	r = requestBuffer -> Construct(headerStr.GetLength() + (shot->GetSize()) + delimiterStr.GetLength());
	AppLog("Buffer create result: (%s)\n", GetErrorMessage(r));

	r = requestBuffer -> CopyFrom(*(StringUtil::StringToUtf8N(headerStr)));
	AppLog("Header copy result: (%s)\n", GetErrorMessage(r));

	r = requestBuffer -> CopyFrom(*(shot->GetBytes()));
	AppLog("File copy result: (%s)\n", GetErrorMessage(r));

	r = requestBuffer -> CopyFrom(*(StringUtil::StringToUtf8N(delimiterStr)));
	AppLog("Delimiter copy result: (%s)\n", GetErrorMessage(r));


	AppLog("Sending:%S", headerStr.GetPointer());

//	r = s->Send(*(StringUtil::StringToUtf8N(headerStr)));

//	int sent = 0;
//	int& reallySent = sent;
//
//	int CHUNK_SIZE = 10000;
//	byte chunk[shot->GetSize()>CHUNK_SIZE?CHUNK_SIZE:shot->GetSize()];
//	int offset = 0;
//	while (offset < shot->GetSize()) {
//		requestBuffer -> GetArray(chunk, offset, CHUNK_SIZE);
//		r = socket->Send(chunk, (int)(shot->GetSize()), reallySent);
//		AppLog("Socket Send result: (%s) bytes sent %d\n", GetErrorMessage(r), reallySent);
//		offset += CHUNK_SIZE;
//	}

//	r = socket -> Send(*requestBuffer);
	r = socket->Send(*(StringUtil::StringToUtf8N(headerStr)));

	AppLog("Socket Send result: %S\n", GetErrorMessage(r));

}

void ShotSocketSender::OnSocketAccept (Osp::Net::Sockets::Socket &pSocket) {AppLog("OnSocketAccept");}
void ShotSocketSender::OnSocketConnected (Osp::Net::Sockets::Socket &pSocket) {AppLog("OnSocketConnected");}
void ShotSocketSender::OnSocketReadyToReceive (Osp::Net::Sockets::Socket &pSocket) { AppLog("OnSocketReadyToReceive");}

void
ShotSocketSender::OnSocketClosed (Osp::Net::Sockets::Socket &pSocket, Osp::Net::Sockets::NetSocketClosedReason reason) {

	AppLog("OnSocketClosed");

	if (reason == NET_SOCKET_CLOSED_REASON_NONE) {
		AppLog("NET_SOCKET_CLOSED_REASON_NONE");
	} else if (reason == NET_SOCKET_CLOSED_REASON_NORMAL) {
		AppLog("NET_SOCKET_CLOSED_REASON_NORMAL");
	} else if (reason == NET_SOCKET_CLOSED_REASON_TIMEOUT) {
		AppLog("NET_SOCKET_CLOSED_REASON_TIMEOUT");
	} else if (reason == NET_SOCKET_CLOSED_REASON_NETWORK_UNAVAILABLE) {
		AppLog("NET_SOCKET_CLOSED_REASON_NETWORK_UNAVAILABLE");
	} else if (reason == NET_SOCKET_CLOSED_REASON_SYSTEM) {
		AppLog("NET_SOCKET_CLOSED_REASON_SYSTEM");
	}
// mine
//	else if (reason == NET_SOCKET_CLOSED_REASON_NO_CERTIFICATE) {
//		AppLog("NET_SOCKET_CLOSED_REASON_NO_CERTIFICATE");
//	} else if (reason == NET_SOCKET_CLOSED_REASON_BY_USER) {
//		AppLog("NET_SOCKET_CLOSED_REASON_BY_USER");
//	}

	unsigned long zero = 0;
	unsigned long zero1 = 0;
	unsigned long& value = zero;
	unsigned long& value1 = zero1;

	socket -> Ioctl(NET_SOCKET_FIONREAD, value);
	AppLog("Pending bytes in input: %d\n", value);

	socket -> Ioctl(NET_SOCKET_SIOCATMARK, value1);
	AppLog("NET_SOCKET_SIOCATMARK %d\n", value1);

//	NET_SOCKET_FIONREAD  The command to determine the amount of data pending in the network input buffer
//	NET_SOCKET_SIOCATMARK  The command to determine whether all out-of-band data is read

	isReadyToSend = false;
}

void ShotSocketSender::OnSocketReadyToSend (Osp::Net::Sockets::Socket &socket) {
	AppLog("OnSocketReadyToSend");
	isReadyToSend = true;
}
